﻿// MulInstruction.cs
// Contains a class for a mul instruction

using System;

namespace armsim
{
    /// <summary>
    /// A 32 bit Mul Instruction in the Arm Architecture
    /// </summary>
    public class MulInstruction : BaseInstruction 
    {

        /// <summary>
        /// The kind of shift to be shifted by
        /// </summary>
        public uint Rs { get; protected set; }

        /// <summary>
        /// The kind of shift to be shifted by
        /// </summary>
        public uint Rm { get; protected set; }

        /// <summary>
        /// The kind of shift to be shifted by
        /// </summary>
        public uint Rd { get; protected set; }
        
        /// <summary>
        /// Intializes a new MulInstruction
        /// </summary>
        /// <param name="instruction">instruction value to be decoded from</param>
        public MulInstruction(uint instruction) : base(instruction)
        {
            this.Rs = VirtualMemory.ExtractBits(this.Instruction, 8, 11);
            this.Rm = VirtualMemory.ExtractBits(this.Instruction, 0, 3);
            this.Rd = VirtualMemory.ExtractBits(this.Instruction, 16, 19);

        }

        /// <summary>
        /// Executes the Mul Instruction
        /// </summary>
        /// <param name="cpu">Executes from the cpu and stores the results in the cpu</param>
        public override void Execute(VirtualCPU cpu)
        {
            //var rn = cpu.Registers.ReadWord(Memory.MapRegNoToRegMem(this.));
            //var rm = this.Operand2.ComputeValue(cpu);

            var rm = cpu.Registers.ReadRegistersDuringExecute(VirtualMemory.MapRegNoToRegMem(this.Rm));
            var rs = cpu.Registers.ReadRegistersDuringExecute(VirtualMemory.MapRegNoToRegMem(this.Rs));

            ulong answer = rm*rs;
            answer = (answer & 0x00000000FFFFFFFFu);

            cpu.Registers.WriteWord(VirtualMemory.MapRegNoToRegMem(this.Rd), (uint)answer);
        }

        /// <summary>
        /// Converts the Mul instruction to assembly
        /// </summary>
        /// <param name="cpu">cpu to get information from</param>
        /// <returns>the assembly</returns>
        public override String ToAssembly(VirtualCPU cpu)
        {
            return String.Format("MUL {0}, {1}, {2}", VirtualMemory.RegToAssembly(Rd), VirtualMemory.RegToAssembly(Rm), VirtualMemory.RegToAssembly(Rs));
        }

    }

}
